package controllers

import (
	"fmt"
	"go_pure_admin_api/dto"
	"go_pure_admin_api/global"
	"go_pure_admin_api/models"
	"go_pure_admin_api/utils"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/spf13/viper"
)

type UserController struct {
	BaseController
}

// Login 用户登录接口
// @Summary 用户登录
// @Description 用户使用用户名和密码进行登录，成功后返回访问令牌和刷新令牌
// @Tags 用户模块
// @Accept json
// @Produce json
// @Param loginInfo body dto.LoginUserDto true "登录信息"
// @Success 200 {object} controllers.ResponseJson "登录成功"
// @Failure 201 {object} controllers.ResponseJson "登录失败"
// @Failure 500 {object} controllers.ResponseJson "服务器内部错误"
// @Router /public/user/login [post]
func (u *UserController) Login(c *gin.Context) {
	user := models.Users{}
	userDto := dto.LoginUserDto{}
	if err := c.ShouldBindJSON(&userDto); err != nil {
		u.Fail(c, 400, "参数错误:"+err.Error(), nil)
		return
	}
	err := user.QueryUserByName(userDto.UserName)
	if err != nil || !utils.CheckPassword(userDto.Password, user.Password) {
		if err != nil {
			global.Logger.Errorf("用户%s登陆失败:%e", userDto.UserName, err)
		} else {
			global.Logger.Errorf("用户%s登陆失败:密码验证错误", userDto.UserName)
		}
		u.Fail(c, 402, "用户名或密码错误", nil)
		return
	}
	keys := user.GetRoleKeys()
	accessToken, err := utils.GenerateToken(user.Username, user.ID, keys, viper.GetDuration("jwt.tokenExpire"))
	if err != nil {
		u.Fail(c, 500, "生成访问令牌失败:"+err.Error(), nil)
		return
	}
	refreshToken, err := utils.GenerateToken(user.Username, user.ID, keys, viper.GetDuration("jwt.refreshExpire"))
	if err != nil {
		u.Fail(c, 500, "生成刷新令牌失败:"+err.Error(), nil)
		return
	}
	permissions, err := user.GetUserButtonPermissions(user.Username)
	if err != nil {
		u.Fail(c, 500, "查询用户按钮权限失败:"+err.Error(), nil)
		return
	}
	u.Success(c, "登录成功", dto.UserData{
		Avatar:       user.Avatar,
		Nickname:     user.Nickname,
		Username:     user.Username,
		Roles:        keys,
		Permissions:  permissions,
		AccessToken:  accessToken,
		RefreshToken: refreshToken,
		Expires:      time.Now().Add(viper.GetDuration("jwt.tokenExpire")).Format(time.DateTime),
	})
}

// GetAsyncRoutes 获取用户路由菜单
// @Summary 获取用户路由菜单
// @Description 根据当前登录用户获取其权限范围内的路由菜单
// @Tags 用户模块
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} controllers.ResponseJson "获取路由菜单成功"
// @Failure 201 {object} controllers.ResponseJson "获取路由菜单失败"
// @Router /getAsyncRoutes [get]
func (u *UserController) GetAsyncRoutes(c *gin.Context) {
	username := c.GetString("username")
	var user models.Users
	menusRoutes, err := user.GetMenusRouterThereByLoginName(username)
	fmt.Println("menusRoutes:", menusRoutes)
	if err != nil {
		u.Fail(c, 500, "获取路由菜单失败:"+err.Error(), nil)
		return
	}
	u.Success(c, "获取路由菜单成功", menusRoutes)
}

// RefreshToken 刷新访问令牌
// @Summary 刷新访问令牌
// @Description 使用刷新令牌获取新的访问令牌
// @Tags 用户模块
// @Accept json
// @Produce json
// @Param refreshToken body dto.RefreshTokenRequest true "刷新令牌请求参数"
// @Success 200 {object} controllers.ResponseJson "刷新令牌成功"
// @Failure 201 {object} controllers.ResponseJson "刷新令牌失败"
// @Router /refreshToken [post]
func (u *UserController) RefreshToken(c *gin.Context) {
	// 获取刷新token
	var req dto.RefreshTokenRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		u.Fail(c, 400, "参数错误:"+err.Error(), nil)
		return
	}
	// 解析刷新token
	cl, err := utils.ParseTokenHs256(req.RefreshToken)
	if err != nil {
		u.Fail(c, 500, "解析刷新token失败:"+err.Error(), nil)
		return
	}
	// 生成新的访问token
	accessToken, err := utils.GenerateToken(cl.Username, cl.UserId, cl.RoleKeys, viper.GetDuration("jwt.tokenExpire"))
	if err != nil {
		u.Fail(c, 500, "生成新的访问token失败:"+err.Error(), nil)
		return
	}
	u.Success(c, "刷新成功", struct {
		AccessToken  string `json:"accessToken"`
		RefreshToken string `json:"refreshToken"`
		Expires      string `json:"expires"`
	}{
		AccessToken:  accessToken,
		RefreshToken: req.RefreshToken, // 保持原来的刷新token
		Expires:      time.Now().Add(viper.GetDuration("jwt.tokenExpire")).Format(time.DateTime),
	})
}

// GetUserInfo 获取当前登录用户信息
// @Summary 获取当前登录用户信息
// @Description 获取当前登录用户的详细信息
// @Tags 用户模块
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} controllers.ResponseJson "获取用户信息成功"
// @Failure 500 {object} controllers.ResponseJson "获取用户信息失败"
// @Router /public/user/getUserInfo [get]
func (u *UserController) GetUserInfo(c *gin.Context) {
	username := c.GetString("username")
	var user models.Users
	err := user.QueryUserByName(username)
	if err != nil {
		global.Logger.Errorf("用户%s查询用户信息失败:%e", username, err)
		u.Fail(c, 500, "查询用户信息失败:"+err.Error(), nil)
		return
	}
	u.Success(c, "查询用户信息成功", gin.H{
		"id":          user.ID,
		"avatar":      user.Avatar,
		"nickname":    user.Nickname,
		"username":    user.Username,
		"phone":       user.Phone,
		"email":       user.Email,
		"description": user.Description,
	})
}

// GetAllUserList 获取所有用户列表
// @Summary 获取所有用户列表
// @Description 获取系统中所有用户的列表，无需分页
// @Tags 用户模块
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} controllers.ResponseJson "获取用户列表成功"
// @Failure 500 {object} controllers.ResponseJson "获取用户列表失败"
// @Router /public/user/userAllList [get]
func (u *UserController) GetAllUserList(c *gin.Context) {
	list, err := models.GetAllUserList()
	if err != nil {
		u.Fail(c, 500, "获取用户列表失败", err.Error())
		return
	}
	u.Success(c, "获取用户列表成功", list)

}

// GetUserList 获取用户列表（分页）
// @Summary 获取用户列表（分页）
// @Description 根据条件分页获取用户列表
// @Tags 用户模块
// @Accept json
// @Produce json
// @Security Bearer
// @Param userList body dto.GetUserListDto true "查询参数"
// @Success 200 {object} controllers.ResponseJson "获取用户列表成功"
// @Failure 400 {object} controllers.ResponseJson "参数错误"
// @Failure 500 {object} controllers.ResponseJson "获取用户列表失败"
// @Router /user/userList [post]
func (u *UserController) GetUserList(c *gin.Context) {
	var data dto.GetUserListDto
	if err := c.ShouldBindJSON(&data); err != nil {
		u.Fail(c, 400, "参数错误:"+err.Error(), nil)
		return
	}
	var user models.Users
	list, total, err := user.GetUserList(data)
	if err != nil {
		u.Fail(c, 500, "获取用户列表失败:"+err.Error(), nil)
		return
	}
	u.Success(c, "获取用户列表成功", gin.H{
		"list":  list,
		"total": total,
	})
}

// CreateUser 创建用户
// @Summary 创建用户
// @Description 创建新用户
// @Tags 用户模块
// @Accept json
// @Produce json
// @Security Bearer
// @Param createUser body dto.CreateUserDto true "创建用户参数"
// @Success 200 {object} controllers.ResponseJson "添加用户成功"
// @Failure 400 {object} controllers.ResponseJson "参数错误"
// @Failure 500 {object} controllers.ResponseJson "添加用户失败"
// @Router /user/createUser [post]
func (u *UserController) CreateUser(c *gin.Context) {
	var data dto.CreateUserDto
	if err := c.ShouldBindJSON(&data); err != nil {
		u.Fail(c, 400, "参数错误:"+err.Error(), nil)
		return
	}
	password, err := utils.HashPassword(data.Password)
	if err != nil {
		u.Fail(c, 500, "内部服务器错误", nil)
		return
	}
	data.Password = password
	user := models.Users{}
	err = user.CreateUser(data)
	if err != nil {
		u.Fail(c, 500, "添加用户失败:"+err.Error(), nil)
		return
	}
	u.Success(c, "添加用户成功", nil)
}

// UpdateUser 更新用户信息
// @Summary 更新用户信息
// @Description 更新用户信息（不包含密码）
// @Tags 用户模块
// @Accept json
// @Produce json
// @Security Bearer
// @Param updateUser body dto.UpdateUserDto true "更新用户参数"
// @Success 200 {object} controllers.ResponseJson "更新用户成功"
// @Failure 400 {object} controllers.ResponseJson "参数错误"
// @Failure 500 {object} controllers.ResponseJson "更新用户失败"
// @Router /user/updateUser [post]
func (u *UserController) UpdateUser(c *gin.Context) {
	data := dto.UpdateUserDto{}
	if err := c.ShouldBindJSON(&data); err != nil {
		u.Fail(c, 400, "参数错误:"+err.Error(), nil)
		return
	}
	user := models.Users{}
	err := user.UpdateUser(data)
	if err != nil {
		u.Fail(c, 500, "更新用户失败:"+err.Error(), nil)
		return
	}
	u.Success(c, "更新用户成功", nil)
}

// DeleteUser 删除用户
// @Summary 删除用户
// @Description 根据用户ID删除用户
// @Tags 用户模块
// @Accept json
// @Produce json
// @Security Bearer
// @Param deleteUser body dto.DeleteUserDto true "删除用户参数"
// @Success 200 {object} controllers.ResponseJson "删除用户成功"
// @Failure 400 {object} controllers.ResponseJson "参数错误"
// @Failure 500 {object} controllers.ResponseJson "删除用户失败"
// @Router /user/deleteUser [post]
func (u *UserController) DeleteUser(c *gin.Context) {
	data := dto.DeleteUserDto{}
	if err := c.ShouldBindJSON(&data); err != nil {
		u.Fail(c, 400, "参数错误:"+err.Error(), nil)
		return
	}
	user := models.Users{}
	err := user.DeleteUser(data)
	if err != nil {
		global.Logger.Errorf("用户%s删除用户%s失败:%e", c.GetString("username"), user.Username, err)
		u.Fail(c, 500, "删除用户失败:"+err.Error(), nil)
		return
	}
	u.Success(c, "删除用户成功", nil)
}

// GetAllRoleList 获取所有角色列表
// @Summary 获取所有角色列表
// @Description 获取系统中所有角色的列表
// @Tags 用户模块
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} controllers.ResponseJson "获取角色列表成功"
// @Failure 500 {object} controllers.ResponseJson "获取角色列表失败"
// @Router /user/roleList [get]
func (u *UserController) GetAllRoleList(c *gin.Context) {
	list, err := models.GetAllRoleList()
	if err != nil {
		u.Fail(c, 500, "获取角色列表失败:"+err.Error(), nil)
		return
	}
	u.Success(c, "获取角色列表成功", list)
}

// GetUserRoleIds 获取用户角色ID列表
// @Summary 获取用户角色ID列表
// @Description 根据用户ID获取用户拥有的角色ID列表
// @Tags 用户模块
// @Accept json
// @Produce json
// @Security Bearer
// @Param userRoleIds body dto.GetUserRoleIdsDto true "查询用户角色参数"
// @Success 200 {object} controllers.ResponseJson "获取用户角色ID列表成功"
// @Failure 400 {object} controllers.ResponseJson "参数错误"
// @Failure 500 {object} controllers.ResponseJson "获取用户角色ID列表失败"
// @Router /user/listRoleIds [post]
func (u *UserController) GetUserRoleIds(c *gin.Context) {
	var data dto.GetUserRoleIdsDto
	if err := c.ShouldBind(&data); err != nil {
		u.Fail(c, 400, "参数错误:"+err.Error(), nil)
		return
	}
	var user models.Users
	roleIds, err := user.GetUserRoleIds(data)
	if err != nil {
		u.Fail(c, 500, "获取用户角色ID列表失败:"+err.Error(), nil)
		return
	}
	u.Success(c, "获取用户角色ID列表成功", roleIds)
}

// UpdatePassword 更新用户密码
// @Summary 更新用户密码
// @Description 更新指定用户的密码
// @Tags 用户模块
// @Accept json
// @Produce json
// @Security Bearer
// @Param updatePassword body dto.UpdatePasswordDto true "更新密码参数"
// @Success 200 {object} controllers.ResponseJson "更新密码成功"
// @Failure 400 {object} controllers.ResponseJson "参数错误"
// @Failure 500 {object} controllers.ResponseJson "更新密码失败"
// @Router /user/updatePassword [post]
func (u *UserController) UpdatePassword(c *gin.Context) {
	var data dto.UpdatePasswordDto
	var err error
	if err = c.ShouldBind(&data); err != nil {
		u.Fail(c, 400, "参数错误:"+err.Error(), nil)
		return
	}
	var user models.Users
	data.NewPassword, err = utils.HashPassword(data.NewPassword)
	if err != nil {
		u.Fail(c, 500, "更新密码失败:"+err.Error(), nil)
		return
	}
	err = user.UpdatePassword(data)
	if err != nil {
		u.Fail(c, 500, "更新密码失败:"+err.Error(), nil)
		return
	}
	u.Success(c, "更新密码成功", nil)
}

// UpdateUserRole 更新用户角色
// @Summary 更新用户角色
// @Description 更新用户拥有的角色
// @Tags 用户模块
// @Accept json
// @Produce json
// @Security Bearer
// @Param updateUserRole body dto.UpdateUserRoleDto true "更新用户角色参数"
// @Success 200 {object} controllers.ResponseJson "更新用户角色成功"
// @Failure 400 {object} controllers.ResponseJson "参数错误"
// @Failure 500 {object} controllers.ResponseJson "更新用户角色失败"
// @Router /user/updateUserRole [post]
func (u *UserController) UpdateUserRole(c *gin.Context) {
	var data dto.UpdateUserRoleDto
	if err := c.ShouldBindJSON(&data); err != nil {
		u.Fail(c, 400, "参数错误:"+err.Error(), nil)
		return
	}
	var user models.Users
	err := user.UpdateUserRole(data)
	if err != nil {
		u.Fail(c, 500, "更新用户角色失败:"+err.Error(), nil)
		return
	}
	u.Success(c, "更新用户角色成功", nil)
}

// BatchDeleteUser 批量删除用户
// @Summary 批量删除用户
// @Description 根据用户ID列表批量删除用户
// @Tags 用户模块
// @Accept json
// @Produce json
// @Security Bearer
// @Param batchDeleteUser body dto.BatchDeleteUserDto true "批量删除用户参数"
// @Success 200 {object} controllers.ResponseJson "批量删除用户成功"
// @Failure 400 {object} controllers.ResponseJson "参数错误"
// @Failure 500 {object} controllers.ResponseJson "批量删除用户失败"
// @Router /user/batchDeleteUser [post]
func (u *UserController) BatchDeleteUser(c *gin.Context) {
	var data dto.BatchDeleteUserDto
	if err := c.ShouldBindJSON(&data); err != nil {
		u.Fail(c, 400, "参数错误:"+err.Error(), nil)
		return
	}
	err := models.BatchDeleteUser(data)
	if err != nil {
		u.Fail(c, 500, "批量删除用户失败:"+err.Error(), nil)
		return
	}
	u.Success(c, "批量删除用户成功", nil)
}

// UploadAvatar 上传头像
// @Summary 上传头像
// @Description 上传用户头像文件
// @Tags 用户模块
// @Accept multipart/form-data
// @Produce json
// @Security Bearer
// @Param avatar formData file true "头像文件"
// @Success 200 {object} controllers.ResponseJson "上传文件成功"
// @Failure 400 {object} controllers.ResponseJson "上传文件失败"
// @Failure 500 {object} controllers.ResponseJson "保存文件失败"
// @Router /user/uploadAvatar [post]
func (u *UserController) UploadAvatar(c *gin.Context) {
	file, err := c.FormFile("avatar")
	if err != nil {
		u.Fail(c, 500, "上传文件失败:"+err.Error(), nil)
		return
	}
	username := c.GetString("username")
	var user models.Users
	err = user.QueryUserByName(username)
	if err != nil {
		global.Logger.Error(err)
		u.Fail(c, 500, "上传文件失败", nil)
		return
	}

	// 验证文件类型（只允许图片）
	allowedTypes := map[string]bool{
		".jpg":  true,
		".jpeg": true,
		".png":  true,
		".gif":  true,
		".bmp":  true,
		".webp": true,
	}

	ext := strings.ToLower(filepath.Ext(file.Filename))
	if !allowedTypes[ext] {
		u.Fail(c, 500, "不支持的文件类型，仅支持图片文件", nil)
		return
	}

	// 限制文件大小（例如限制为5MB）
	if file.Size > 5*1024*1024 {
		u.Fail(c, 500, "文件大小不能超过5MB", nil)
		return
	}

	uploadPath := "./img/avatar/"
	err = os.MkdirAll(uploadPath, os.ModePerm)
	if err != nil {
		global.Logger.Error(err)
		u.Fail(c, 500, "创建上传目录失败", nil)
		return
	}

	// 使用 UUID 生成唯一文件名，保留原始扩展名
	fileName := uuid.New().String() + ext
	filePath := filepath.Join(uploadPath, fileName)

	// 保存文件
	if err := c.SaveUploadedFile(file, filePath); err != nil {
		global.Logger.Error(err)
		u.Fail(c, 500, "保存文件失败", nil)
		return
	}
	err = user.UpdateAvatar(fileName)
	if err != nil {
		global.Logger.Error(err)
		u.Fail(c, 500, "更新用户头像失败", nil)
		return
	}

	u.Success(c, "上传文件成功", gin.H{
		"filePath": fileName,
	})
}

// GetUserAvatar 获取用户头像
// @Summary 获取用户头像
// @Description 根据文件名获取用户头像图片
// @Tags 用户模块
// @Accept json
// @Produce image/*
// @Security Bearer
// @Param filename path string true "头像文件名"
// @Success 200 {file} file "获取头像成功"
// @Failure 404 {object} controllers.ResponseJson "文件不存在"
// @Router /public/user/getUserAvatar/{filename} [get]
func (u *UserController) GetUserAvatar(c *gin.Context) {
	filename := c.Param("filename")
	if filename == "" {
		u.Fail(c, 400, "参数错误", nil)
		return
	}
	fmt.Println("filename:", filename)
	// 拼接图片路径
	filePath := filepath.Join("./img/avatar/", filename)

	// 检查文件是否存在
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		u.Fail(c, http.StatusNotFound, "文件不存在", nil)
		return
	}

	// 设置 Content-Type 以确保图片能够正确显示
	// 把文件
	c.File(filePath)
}

// UpdateUserInfo 更新当前登录用户信息
// @Summary 更新当前登录用户信息
// @Description 更新当前登录用户的基本信息（头像、昵称、电话、邮箱、描述）
// @Tags 用户模块
// @Accept json
// @Produce json
// @Security Bearer
// @Param updateUserInfo body dto.UpdateUserInfoDto true "更新用户信息参数"
// @Success 200 {object} controllers.ResponseJson "更新用户信息成功"
// @Failure 400 {object} controllers.ResponseJson "参数错误"
// @Failure 500 {object} controllers.ResponseJson "更新用户信息失败"
// @Router /public/user/updateUserInfo [post]
func (u *UserController) UpdateUserInfo(c *gin.Context) {
	var data dto.UpdateUserInfoDto
	if err := c.ShouldBindJSON(&data); err != nil {
		u.Fail(c, 400, "参数错误:"+err.Error(), nil)
		return
	}
	err := models.UpdateUserInfo(data)
	if err != nil {
		u.Fail(c, 500, "更新用户信息失败:"+err.Error(), nil)
		return
	}
	u.Success(c, "更新用户信息成功", nil)
}

// UpdateUserPassword 更新当前登录用户密码
// @Summary 更新当前登录用户密码
// @Description 允许用户更新自己的密码
// @Tags 用户模块
// @Accept json
// @Produce json
// @Security Bearer
// @Param updateUserPassword body dto.UpdateUserPasswordDto true "更新用户密码参数"
// @Success 200 {object} controllers.ResponseJson "更新用户密码成功"
// @Failure 400 {object} controllers.ResponseJson "参数错误"
// @Failure 500 {object} controllers.ResponseJson "更新用户密码失败"
// @Router /public/user/updateUserPassword [post]
func (u *UserController) UpdateUserPassword(c *gin.Context) {
	var data dto.UpdateUserPasswordDto
	if err := c.ShouldBindJSON(&data); err != nil {
		u.Fail(c, 400, "参数错误:"+err.Error(), nil)
		return
	}
	err := models.UpdateUserPassword(data)
	if err != nil {
		global.Logger.Errorf("用户%s更新密码失败:%e", c.GetString("username"), err)
		u.Fail(c, 500, err.Error(), nil)
		return
	}
	u.Success(c, "更新用户密码成功", nil)
}
